package com.szholly.plug.safe.security;

import java.io.IOException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.session.SessionAuthenticationStrategy;

import com.szholly.utils.session.SessionFactory;
import com.szholly.utils.session.provider.ISessionProvider;
import com.szholly.utils.util.CookieUtils;
import com.szholly.utils.util.StringUtils;
import com.szholly.data.general.QueryMap;
import com.szholly.plug.safe.entity.user.OrgEntity;
import com.szholly.plug.safe.entity.user.OrgService;
import com.szholly.plug.safe.entity.user.UserEntity;

/**
 * 自定义登录评证过滤器
 */
public class CustomerAuthenticationProcessingFilter extends
		UsernamePasswordAuthenticationFilter {

	public static final String VALIDATE_CODE = "validateCode";
	public static final String ORG_ID = "orgid";
	public static final String USERNAME = "username";
	public static final String PASSWORD = "password";

	@SuppressWarnings("unused")
	private SessionAuthenticationStrategy sessionStrategy;

	public void setSessionStrategy(SessionAuthenticationStrategy sessionStrategy) {
		this.sessionStrategy = sessionStrategy;
		this.setSessionAuthenticationStrategy(sessionStrategy);
	}

	@Override
	public Authentication attemptAuthentication(HttpServletRequest request,
			HttpServletResponse response) throws AuthenticationException {
		if (!request.getMethod().equals("POST")) {
			throw new AuthenticationServiceException("登录验证方法不支持以下提交方式: "
					+ request.getMethod());
		}
		// 检测验证码
		checkValidateCode(request);

		// 验证用户账号与密码是否对应
		String username = obtainUsername(request);
		String password = obtainPassword(request);
		
		if (StringUtils.IsNullOrEmpty(username) || StringUtils.IsNullOrEmpty(password)) {
			throw new AuthenticationServiceException("用户名密码不能为空");
		}
		
		String orgid = obtainOrgId(request);// TODO 扩展组织机构验证

		// UsernamePasswordAuthenticationToken实现 Authentication
//		UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(
//				username, password);
		UsernamePasswordAuthenticationTokenExt authRequest = new UsernamePasswordAuthenticationTokenExt(
				username, password);
		authRequest.setOrgid(orgid);
		// 允许子类设置详细属性
		setDetails(request, authRequest);

		// 运行UserDetailsService的loadUserByUsername 再次封装Authentication
		Authentication authentication = this.getAuthenticationManager()
				.authenticate(authRequest);
		return authentication;
	}

	@SuppressWarnings("unchecked")
	protected void successfulAuthentication(HttpServletRequest request,
			HttpServletResponse response, FilterChain chain,
			Authentication authResult) throws IOException, ServletException {
		// 初始化用户信息
		UserEntity userEntity = CustomAccessDecisionManager.initUserRole(authResult);
		List<String> functionTag = null;
		List<String> functionUrl = null;
		if(userEntity.getIsSuperAdmin()){
			functionTag = new ArrayList<String>();
			functionUrl = new ArrayList<String>();
			
			functionTag.add("sa");
			functionUrl.add("sa");
		} else {
			// 将功能权限，url权限放到用户的cookie中
			ISessionProvider session = SessionFactory.getSession();
			functionTag = (List<String>)session.getObject(ISessionProvider.Function);
			functionUrl = (List<String>)session.getObject(ISessionProvider.FunctionUrl);
		}
		
		String tagString = "";
		for(String item : functionTag){
			tagString += item+",";
		}
		if(!tagString.equals("")){
			tagString = tagString.substring(0, tagString.length()-1);
		}
		CookieUtils.addCookie(request, response, CookieUtils.Security_Tag, tagString, null, null);
		
		String urlString = "";
		for(String item : functionUrl){
			urlString += item+",";
		}
		urlString = urlString.equals("") ? "" : urlString.substring(0, urlString.length()-1);
		CookieUtils.addCookie(request, response, CookieUtils.Security_Url, urlString, null, null);
		// 用户ID
		CookieUtils.addCookie(request, response, CookieUtils.Security_UserID, userEntity.getUserID(), null, null);
		
		// 用户真实名称
		String name = userEntity.getUserRealName();
		if(StringUtils.IsNullOrSpace(name)){
			CookieUtils.addCookie(request, response, CookieUtils.Security_UserRealName, "", null, null);
		}else{
			name = URLEncoder.encode(name, "utf-8");
			CookieUtils.addCookie(request, response, CookieUtils.Security_UserRealName, name, null, null);
		}
		
		// 单位
		name = userEntity.getDW();
		if(StringUtils.IsNullOrSpace(name)){
			CookieUtils.addCookie(request, response, CookieUtils.Security_UserDw, "", null, null);
		}else{
			name = URLEncoder.encode(name, "utf-8");
			CookieUtils.addCookie(request, response, CookieUtils.Security_UserDw, name, null, null);
		}
		
		// 机构
		name = userEntity.getOrgName();
		if(StringUtils.IsNullOrSpace(name)){
			CookieUtils.addCookie(request, response, CookieUtils.Security_UserOrg, "", null, null);
		}else{
			name = URLEncoder.encode(name, "utf-8");
			CookieUtils.addCookie(request, response, CookieUtils.Security_UserOrg, name, null, null);
		}
		
		// 机构Id
		name = userEntity.getOrgID();
		if(StringUtils.IsNullOrSpace(name)){
			CookieUtils.addCookie(request, response, CookieUtils.Security_Orgbh, "", null, null);
		}else{
			name = URLEncoder.encode(name, "utf-8");
			CookieUtils.addCookie(request, response, CookieUtils.Security_Orgbh, name, null, null);
		}
		
		// 部门
		name = userEntity.getDEPTName();
		if(StringUtils.IsNullOrSpace(name)){
			CookieUtils.addCookie(request, response, CookieUtils.Security_DeptName, "", null, null);
		}else{
			name = URLEncoder.encode(name, "utf-8");
			CookieUtils.addCookie(request, response, CookieUtils.Security_DeptName, name, null, null);
		}
		
		// 部门所在政区
		QueryMap qm = new QueryMap();
		HashMap<String,Object> map = new HashMap<String,Object>();
		map.put(OrgEntity.FIELD_ORGID, userEntity.getOrgID());
		qm.setWhereMap(map);
		OrgEntity org = OrgService.getSingleRef().getEntity(OrgEntity.class, qm);
		if(org != null){
			name = org.getOrgBH();
		}else{
			name = null;
		}
		if(StringUtils.IsNullOrSpace(name)){
			CookieUtils.addCookie(request, response, CookieUtils.Security_Orgbh, "", null, null);
		}else{
			name = URLEncoder.encode(name, "utf-8");
			CookieUtils.addCookie(request, response, CookieUtils.Security_Orgbh, name, null, null);
		}
		
		super.successfulAuthentication(request, response, chain, authResult);
	}

	/**
	 * 验证验证码
	 * 
	 * @param request
	 */
	protected void checkValidateCode(HttpServletRequest request) {
/*		 HttpSession session = request.getSession();
		 String sessionValidateCode = obtainSessionValidateCode(session);
		 // 让上一次的验证码失效
		 session.setAttribute(VALIDATE_CODE, null);
		 String validateCodeParameter = obtainValidateCodeParameter(request);
		 if (StringUtils.IsNullOrEmpty(validateCodeParameter)
		 || !sessionValidateCode.equalsIgnoreCase(validateCodeParameter)) {
		 throw new AuthenticationServiceException("验证码错误！");
		 }*/
	}

	@SuppressWarnings("unused")
	private String obtainValidateCodeParameter(HttpServletRequest request) {
		Object obj = request.getParameter(VALIDATE_CODE);
		return null == obj ? "" : obj.toString();
	}

	protected String obtainSessionValidateCode(HttpSession session) {
		Object obj = session.getAttribute(VALIDATE_CODE);
		return null == obj ? "" : obj.toString();
	}
	protected String obtainOrgId(HttpServletRequest request) {
		Object obj = request.getParameter(ORG_ID);
		if(null == obj || "".equals(obj)){
			return "-1";
		}
		return obj.toString();
	}
	@Override
	protected String obtainUsername(HttpServletRequest request) {
		Object obj = request.getParameter(USERNAME);
		return null == obj ? "" : obj.toString();
	}

	@Override
	protected String obtainPassword(HttpServletRequest request) {
		Object obj = request.getParameter(PASSWORD);
		return null == obj ? "" : obj.toString();
	}
}